from django.shortcuts import redirect
from django.contrib import messages
from django.urls import resolve, reverse
from django.contrib.auth import logout
from .models import SystemConfig, AdminLog
from .session import AdminSessionStore
import ipaddress
import time
from django.utils import timezone
from user.models import UserProfile
import re
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.conf import settings

class SystemSettingsMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 从数据库获取系统设置
        try:
            settings = SystemConfig.objects.first()
            if settings is None:
                # 如果没有设置，创建默认设置
                settings = SystemConfig.objects.create(
                    key="site_settings",
                    value={
                        "site_name": "故事生成系统",
                        "site_description": "AI故事生成和分享平台",
                        "allow_registration": True,
                        "allow_story_creation": True,
                        "maintenance_mode": False
                    },
                    description="系统基本设置"
                )
        except Exception as e:
            # 如果出现异常（例如表不存在），不做任何操作
            print(f"SystemSettings error: {e}")
            return self.get_response(request)

        # 排除部分路径
        try:
            url_resolver = resolve(request.path_info)
            current_url = url_resolver.url_name
        except:
            current_url = ""
            
        exclude_paths = ['admin:index', 'admin_login', 'login']
        
        # 检查维护模式
        settings_value = settings.value
        if settings_value.get('maintenance_mode', False) and not request.user.is_superuser:
            # 如果当前请求不是维护页面和登录页面
            if current_url not in exclude_paths:
                messages.warning(request, "系统正在维护中，请稍后再试")
                return redirect('home')  # 重定向到首页或维护页面

        # 检查注册权限
        if current_url == 'register' and not settings_value.get('allow_registration', True):
            messages.warning(request, "系统当前不允许新用户注册")
            return redirect('home')

        # 检查故事创建权限
        if current_url and 'story_create' in current_url and not settings_value.get('allow_story_creation', True):
            if not request.user.is_superuser:  # 管理员可以跳过此限制
                messages.warning(request, "系统当前不允许创建新故事")
                return redirect('story_list')

        # 检查是否访问的是静态文件或媒体文件
        if '/media/' in request.path or '/static/' in request.path:
            # 对于静态文件和媒体文件，直接通过
            pass

        response = self.get_response(request)
        return response


class AdminLogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 保存请求开始时间
        request.start_time = time.time()
        response = self.get_response(request)
        
        # 检查是否是管理员操作
        if request.user.is_authenticated and (request.user.is_staff or request.user.is_superuser):
            # 只记录POST, DELETE, PUT, PATCH请求
            if request.method in ['POST', 'DELETE', 'PUT', 'PATCH']:
                # 获取客户端IP
                x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
                if x_forwarded_for:
                    ip = x_forwarded_for.split(',')[0]
                else:
                    ip = request.META.get('REMOTE_ADDR')
                
                # 获取当前URL名称
                try:
                    url_name = resolve(request.path_info).url_name
                    # 只记录管理操作
                    if url_name and ('admin' in url_name or 'delete' in url_name or 'edit' in url_name):
                        # 计算响应时间
                        execution_time = time.time() - request.start_time
                        
                        # 记录操作详情
                        action_type = 'other'  # 默认为其他操作
                        if 'delete' in url_name:
                            action_type = 'delete_story'
                        elif 'edit' in url_name:
                            action_type = 'edit_story'
                        
                        description = f"{request.method} {url_name} - 路径: {request.path}"
                        if request.method == 'POST':
                            post_data = request.POST.copy()
                            # 移除敏感字段
                            for key in ['password', 'password1', 'password2', 'csrfmiddlewaretoken']:
                                if key in post_data:
                                    post_data[key] = '[FILTERED]'
                            description += f" - 数据: {dict(post_data)}"
                        
                        # 保存日志
                        AdminLog.objects.create(
                            admin=request.user,
                            action_type=action_type,
                            description=description,
                            created_at=timezone.now(),
                            ip_address=ip
                        )
                except Exception as e:
                    # 记录错误但不中断请求
                    print(f"Error logging admin action: {e}")
        
        return response 

# 用户封禁中间件
class UserBanMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 检查用户是否已认证且被封禁
        if request.user.is_authenticated and not (request.user.is_staff or request.user.is_superuser):
            try:
                profile = UserProfile.objects.get(user=request.user)
                if profile.is_banned:
                    # 允许用户访问的URL白名单
                    allowed_urls = ['/user/logout/', '/user/banned/']
                    if not any(request.path.startswith(url) for url in allowed_urls):
                        messages.error(request, '您的账号已被封禁，详情请查看封禁原因。')
                        return redirect('user:banned')  # 重定向到封禁页面
            except UserProfile.DoesNotExist:
                pass
                
        response = self.get_response(request)
        return response

# 管理员会话中间件
class AdminSessionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 检查是否访问管理员页面
        is_admin_url = request.path.startswith('/adminuser/') and not request.path.startswith('/adminuser/login/')
        is_admin_login = request.path.startswith('/adminuser/login/')
        
        # 获取管理员会话Cookie名称
        admin_cookie_name = getattr(settings, 'ADMIN_SESSION_COOKIE_NAME', 'admin_sessionid')
        
        # 检查是否有管理员会话
        if admin_cookie_name in request.COOKIES and not is_admin_login:
            admin_session_key = request.COOKIES.get(admin_cookie_name)
            
            # 尝试从管理员会话加载用户
            try:
                admin_session = AdminSessionStore(admin_session_key)
                user_id = admin_session.get('_auth_user_id')
                
                # 如果找到用户ID，加载用户
                if user_id:
                    User = get_user_model()
                    try:
                        user = User.objects.get(pk=user_id)
                        # 只有管理员可以使用管理员会话
                        if user.is_staff or user.is_superuser:
                            # 在管理员页面上设置用户
                            request.user = user
                            request._admin_user = user  # 标记为管理员用户
                            
                            # 如果需要在管理员会话中使用CSRF令牌
                            # 我们使用管理员会话的会话存储
                            request.session = admin_session
                    except User.DoesNotExist:
                        pass
            except Exception as e:
                # 忽略会话错误，继续正常流程
                pass
        
        # 如果是管理员页面但用户未被标记为管理员
        if is_admin_url and not hasattr(request, '_admin_user'):
            messages.error(request, '您没有权限访问管理员页面')
            return redirect('adminuser:admin_login')
        
        # 确保管理员登录页面总是设置新的CSRF令牌
        if is_admin_login:
            from django.middleware.csrf import get_token
            get_token(request)
            
        response = self.get_response(request)
        return response 